package com.demo2do.fms.entity.vehicle.source;

import java.util.Date;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.persistence.Transient;

import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.hibernate.annotations.DynamicInsert;
import org.hibernate.annotations.DynamicUpdate;
import org.springframework.format.annotation.DateTimeFormat;

import com.demo2do.fms.entity.authority.Organization;
import com.demo2do.fms.entity.supplier.common.Supplier;
import com.demo2do.fms.entity.vehicle.VehicleStatus;
import com.demo2do.fms.entity.vehicle.tractor.Tractor;
import com.demo2do.fms.entity.vehicle.tractor.TractorModifiedVersion;
import com.demo2do.fms.entity.vehicle.trailer.Trailer;

/**
 * 车辆基本信息
 * 
 * @author mohanlan
 *
 */
@Entity
@Table(name = "FMS_VEHICLE_SOURCE")
@DynamicInsert
@DynamicUpdate
public class VehicleSource {
    
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "generator")
    @SequenceGenerator(name = "generator", sequenceName = "HIBERNATE_SEQUENCE", allocationSize = 1)
    private Long id;
    
    /** 公司ID */
    @ManyToOne(fetch = FetchType.LAZY, optional = true)
    @JoinColumn(name = "organization_id", referencedColumnName = "id")
    private Organization organization;
    
    /** 所属供方 */
    @ManyToOne(fetch = FetchType.LAZY, optional = true)
    @JoinColumn(name = "supplier_id", referencedColumnName = "id")
    private Supplier supplier;

    /** 车辆编号 */
    @Column(name = "VEHICLE_CODE")
    private String code;
    
    /** 牵引车id */
    private Long tractorId;
    
    /** 牵引车中文车牌 */
    private String tractorBrandCode;
    
    /** 牵引车英文车牌 */
    @Column(name = "TRACTOR_EN_BRAND_CODE")
    private String tractorENBrandCode;
    
    /** 挂车 */
    private Long trailerId;
    
    /** 挂车中文车牌 */
    private String trailerBrandCode;
    
    /** 车辆同步状态 */
    @Enumerated(EnumType.STRING)
    private SyncStatus status;
    
    /** 车辆状态 */
    @Enumerated(EnumType.STRING)
    private VehicleStatus vehicleStatus;
    
    /** 是否同步 */
    @Column(name = "IS_SYNCHRONIZE")
    private Boolean synchronize;
    
    /** 是否锁定 */
    @Column(name = "IS_LOCK")
    private Boolean lock;
    
    /** 锁定类型 */
    @Enumerated(EnumType.STRING)
    private LockType lockType;
    
    /** 锁定备注 */
    private String lockReason;
    
    /** 驳回理由 */
    private String rejectReason;

    /** 引入申报时间 */
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    private Date declareTime;
    
    /** 是否来自VAM */
    @Column(name = "is_vam")
    private boolean vam;

    @Column(name = "CREATOR")
    private Long creator;

    @Column(name = "CREATE_TIME")
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date createTime;

    @Column(name = "LAST_OPERATOR")
    private Long lastOperator;

    @Column(name = "LAST_MODIFY_TIME")
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date lastModifyTime;

    /** 是否注销 */
    @Column(name = "IS_DISABLED")
    private Boolean disabled;

    /**
     * The default constructor
     */
    public VehicleSource() {
    }
    
    /**
     * 救援车初始化
     * 
     * @param tractor
     * @param supplier
     * @param organization
     * @param createTime
     * @param creator
     * @return
     */
    public VehicleSource(Tractor tractor, Supplier supplier, Organization organization, Date createTime, Long creator) {
        
        this.tractorId = tractor.getId();
        this.tractorENBrandCode = tractor.getBrandENCode();
        this.tractorBrandCode = tractor.getBrandCNCode();
        this.code = tractor.getCode();
        
        this.supplier = supplier;
        this.organization = organization;
        
        this.status = SyncStatus.UNSYNC;
        this.vehicleStatus = VehicleStatus.NORMAL;
        this.synchronize = false;
        this.lock = false;
        
        this.creator = creator;
        this.createTime = createTime;
        this.lastOperator = creator; 
        this.lastModifyTime = createTime;
        this.disabled = false;
    }
    
    /**
     * 非救援车初始化
     * 
     * @param tractor
     * @param trailer
     * @param supplier
     * @param organization
     * @param createTime
     * @param creator
     * @return
     */
    public VehicleSource(Tractor tractor, Trailer trailer, Supplier supplier, Organization organization, Date createTime, Long creator) {
        
        this.tractorId = tractor.getId();
        this.trailerId = trailer.getId();
        this.tractorBrandCode = tractor.getBrandCNCode();
        this.trailerBrandCode = trailer.getBrandCNCode();
        this.tractorENBrandCode = tractor.getBrandENCode();
        this.code = tractor.getCode();
        
        this.supplier = supplier;
        this.organization = organization;
        
        this.status = SyncStatus.UNSYNC;
        this.vehicleStatus = VehicleStatus.NORMAL;
        this.synchronize = false;
        this.lock = false;
        
        this.creator = creator;
        this.createTime = createTime;
        this.lastOperator = creator; 
        this.lastModifyTime = createTime;
        this.disabled = false;
    }
    
    /**
     * @return
     */
    public boolean couldBind() {
    	return status.isSynced() && BooleanUtils.isTrue(synchronize);
    }
    
    /**
     * 换挂
     * 
     * @param trailer
     * @return
     */
    public VehicleSource editTrailer(Trailer trailer) {
        this.trailerId = trailer.getId();
        this.trailerBrandCode = trailer.getBrandCNCode();
        return this;
    }
    
    /**
     * @param operator
     * @return
     */
    public VehicleSource declare(Long operator) {
        this.status = SyncStatus.SYNCING;
        this.declareTime = new Date();
        this.lastOperator = operator;
        this.lastModifyTime = new Date();
        return this;
    }
    
    /**
     * @param operator
     * @return
     */
    public VehicleSource cancelDeclare(Long operator) {
        this.status = SyncStatus.UNSYNC;
        this.declareTime = null;
        this.lastOperator = operator;
        this.lastModifyTime = new Date();
        return this;
    }
    
    /**
     * 标记已同步
     * 
     * @param operator
     * @param now
     * @return
     */
    public VehicleSource sign(Long operator, Date now) {
        
        this.synchronize = true;
        this.status = SyncStatus.SYNCED;
        
        this.lastOperator = operator;
        this.lastModifyTime = now;
        return this;
        
    }

    /**
     * @return
     */
    public boolean hasCode() {
        return StringUtils.isNotBlank(code);
    }
    
    /**
     * 是否有挂车
     * 
     * @return
     */
    public boolean hasTrailer() {
        return trailerId != null;
    }
    
    /**
     * @param code
     * @return
     */
    public VehicleSource editCode(String code) {
        this.code = code;
        return this;
    }
    
    /**
     * @param vam
     * @return
     */
    public VehicleSource editVam(boolean vam) {
        this.vam = vam;
        return this;
    }
    
    /**
     * @param operator
     * @return
     */
    public VehicleSource reject(Long operator) {
        this.status = SyncStatus.REJECTED;
        this.lastOperator = operator;
        this.lastModifyTime = new Date();
        return this;
    }

    /**
     * @return
     */
    @Transient
    public boolean isSynchronize() {
        return BooleanUtils.isTrue(synchronize);
    }
    
    /**
     * @return
     */
    public boolean couldUnlock() {
        return BooleanUtils.isTrue(this.lock) 
            && this.isSynchronize()
            && this.lockType != null
            && this.lockType.isShipmentException();
    }
    
    /**
     * @return
     */
    public boolean couldLock() {
        return BooleanUtils.isFalse(this.lock)
            && this.isSynchronize();
    }
    
    /**
     * @param lock
     * @param lockType
     * @param lockReason
     * @return
     */
    public VehicleSource syncLockInfo(Boolean lock, LockType lockType, String lockReason) {
        this.lock = lock;
        this.lockType = lockType;
        this.lockReason = lockReason;
        return this;
    }
    
    /**
     * 
     * @param reason
     * @param type
     * @param operator
     * @param lastModifyTime
     * @return
     */
    public VehicleSource doLock(String reason, LockType type, Long operator, Date lastModifyTime) {
        this.lock = true;
        this.lockReason = reason;
        this.lockType = type;
        this.lastOperator = operator;
        this.lastModifyTime = lastModifyTime;
        return this;
    }

    /**
    * @description 自动锁车
    * @params [reason, type, lastModifyTime]
    * @return com.demo2do.fms.entity.vehicle.source.VehicleSource
    * @author LZJ
    * @date 2020/12/2 16:37
    **/
    public VehicleSource doLock(String reason, LockType type, Date lastModifyTime) {
        this.lock = true;
        this.lockReason = reason;
        this.lockType = type;
        this.lastModifyTime = lastModifyTime;
        return this;
    }
    
    /**
     * 
     * @param operator
     * @param lastModifyTime
     * @return
     */
    public VehicleSource unlock(Long operator, Date lastModifyTime) {
        this.lock = false;
        this.lockReason = null;
        this.lockType = null;
        this.lastOperator = operator;
        this.lastModifyTime = lastModifyTime;
        return this;
    }
    
    /**
     * 
     * @return
     */
    @Transient
    public boolean isLock() {
        return this.lock;
    }
    
    /**
     * 
     * @param operator
     * @return
     */
    public VehicleSource out(Long operator) {
        this.disabled = true;
        this.vehicleStatus = VehicleStatus.OUT;
        this.lastOperator = operator;
        this.lastModifyTime = new Date();
        return this;
    }
    
    /**
     * @param version
     * @param operator
     * @return
     */
    public VehicleSource adoptModified(TractorModifiedVersion version, Long operator) {
        this.lastOperator = operator;
        this.lastModifyTime = new Date();
        return this;
    }
    
    /**
     * @param operator
     * @return
     */
    public VehicleSource disable(Long operator) {
        this.disabled = true;
        this.lastOperator = operator;
        this.lastModifyTime = new Date();
        return this;
    }

    /**
     * @param lastModifyTime
     * @param lastOperator
     * @return
     */
    public VehicleSource operate(Date lastModifyTime, Long lastOperator) {
        this.lastModifyTime = lastModifyTime;
        this.lastOperator = lastOperator;
        return this;
    }
    
    /**
     * @return the id
     */
    public Long getId() {
        return id;
    }

    /**
     * @return the organization
     */
    public Organization getOrganization() {
        return organization;
    }

    /**
     * @return the supplier
     */
    public Supplier getSupplier() {
        return supplier;
    }

    /**
     * @return the code
     */
    public String getCode() {
        return code;
    }

    /**
     * @return the tractorId
     */
    public Long getTractorId() {
        return tractorId;
    }

    /**
     * @return the tractorENBrandCode
     */
    public String getTractorENBrandCode() {
        return tractorENBrandCode;
    }
    
    /**
     * @return the tractorBrandCode
     */
    public String getTractorBrandCode() {
        return tractorBrandCode;
    }

    /**
     * @return the trailerId
     */
    public Long getTrailerId() {
        return trailerId;
    }

    /**
     * @return the trailerBrandCode
     */
    public String getTrailerBrandCode() {
        return trailerBrandCode;
    }

    /**
     * @return
     */
    public SyncStatus getStatus() {
        return status;
    }

    /**
     * @return the vehicleStatus
     */
    public VehicleStatus getVehicleStatus() {
        return vehicleStatus;
    }

    /**
     * @return
     */
    public Boolean getSynchronize() {
        return synchronize;
    }
    
    /**
     * @return the lock
     */
    public Boolean getLock() {
        return lock;
    }

    /**
     * @return the lockType
     */
    public LockType getLockType() {
        return lockType;
    }

    /**
     * @return the lockReason
     */
    public String getLockReason() {
        return lockReason;
    }

    /**
     * @return the disabled
     */
    public Boolean getDisabled() {
        return disabled;
    }

    /**
     * @return the createTime
     */
    public Date getCreateTime() {
        return createTime;
    }

    /**
     * @return the creator
     */
    public Long getCreator() {
        return creator;
    }

    /**
     * @return the lastModifyTime
     */
    public Date getLastModifyTime() {
        return lastModifyTime;
    }

    /**
     * @return the lastOperator
     */
    public Long getLastOperator() {
        return lastOperator;
    }

    /**
     * @return the rejectReason
     */
    public String getRejectReason() {
        return rejectReason;
    }

    /**
     * @return the declareTime
     */
    public Date getDeclareTime() {
        return declareTime;
    }
    
    /**
     * @return
     */
    public boolean isVam() {
        return vam;
    }

    /**
     * @param id the id to set
     */
    public void setId(Long id) {
        this.id = id;
    }

    /**
     * @param organization the organization to set
     */
    public void setOrganization(Organization organization) {
        this.organization = organization;
    }

    /**
     * @param supplier the supplier to set
     */
    public void setSupplier(Supplier supplier) {
        this.supplier = supplier;
    }

    /**
     * @param code the code to set
     */
    public void setCode(String code) {
        this.code = code;
    }

    /**
     * @param tractorId the tractorId to set
     */
    public void setTractorId(Long tractorId) {
        this.tractorId = tractorId;
    }

    /**
     * @param tractorENBrandCode the tractorENBrandCode to set
     */
    public void setTractorENBrandCode(String tractorENBrandCode) {
        this.tractorENBrandCode = tractorENBrandCode;
    }

    /**
     * @param tractorBrandCode the tractorBrandCode to set
     */
    public void setTractorBrandCode(String tractorBrandCode) {
        this.tractorBrandCode = tractorBrandCode;
    }

    /**
     * @param trailerId the trailerId to set
     */
    public void setTrailerId(Long trailerId) {
        this.trailerId = trailerId;
    }

    /**
     * @param trailerBrandCode the trailerBrandCode to set
     */
    public void setTrailerBrandCode(String trailerBrandCode) {
        this.trailerBrandCode = trailerBrandCode;
    }

    /**
     * @param status
     */
    public void setStatus(SyncStatus status) {
        this.status = status;
    }

    /**
     * @param vehicleStatus the vehicleStatus to set
     */
    public void setVehicleStatus(VehicleStatus vehicleStatus) {
        this.vehicleStatus = vehicleStatus;
    }

    /**
     * @param synchronize
     */
    public void setSynchronize(Boolean synchronize) {
        this.synchronize = synchronize;
    }
    
    /**
     * @param lock the lock to set
     */
    public void setLock(Boolean lock) {
        this.lock = lock;
    }

    /**
     * @param lockType the lockType to set
     */
    public void setLockType(LockType lockType) {
        this.lockType = lockType;
    }

    /**
     * @param lockReason the lockReason to set
     */
    public void setLockReason(String lockReason) {
        this.lockReason = lockReason;
    }

    /**
     * @param disabled the disabled to set
     */
    public void setDisabled(Boolean disabled) {
        this.disabled = disabled;
    }

    /**
     * @param createTime the createTime to set
     */
    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }

    /**
     * @param creator the creator to set
     */
    public void setCreator(Long creator) {
        this.creator = creator;
    }

    /**
     * @param lastModifyTime the lastModifyTime to set
     */
    public void setLastModifyTime(Date lastModifyTime) {
        this.lastModifyTime = lastModifyTime;
    }

    /**
     * @param lastOperator the lastOperator to set
     */
    public void setLastOperator(Long lastOperator) {
        this.lastOperator = lastOperator;
    }

    /**
     * @param rejectReason the rejectReason to set
     */
    public void setRejectReason(String rejectReason) {
        this.rejectReason = rejectReason;
    }

    /**
     * @param declareTime the declareTime to set
     */
    public void setDeclareTime(Date declareTime) {
        this.declareTime = declareTime;
    }
    
    /**
     * @param vam
     */
    public void setVam(boolean vam) {
        this.vam = vam;
    }
    
}